import { DataTypes, Model, Optional, Sequelize, Association } from 'sequelize';
import { sequelize } from '../config/database';
import { User } from './User';
import { Circle } from './Circle';
import { CirclePostLike } from './CirclePostLike';

interface CirclePostAttributes {
    id: number;
    content: string;
    images?: string[] | null;
    authorId: number;
    circleId: number;
    likeCount: number;
    commentCount: number;
    isTop: boolean;
    isEssence: boolean;
    createdAt?: Date;
    updatedAt?: Date;
}

interface CirclePostCreationAttributes extends Optional<CirclePostAttributes, 'id' | 'likeCount' | 'commentCount' | 'isTop' | 'isEssence' | 'createdAt' | 'updatedAt'> { }

export class CirclePost extends Model<CirclePostAttributes, CirclePostCreationAttributes> implements CirclePostAttributes {
    public id!: number;
    public content!: string;
    public images?: string[] | null;
    public authorId!: number;
    public circleId!: number;
    public likeCount!: number;
    public commentCount!: number;
    public isTop!: boolean;
    public isEssence!: boolean;

    public readonly author?: User;
    public readonly circle?: Circle;
    public readonly likers?: User[];

    public static associations: {
        author: Association<CirclePost, User>;
        circle: Association<CirclePost, Circle>;
        likers: Association<CirclePost, User>;
    };

    public readonly createdAt!: Date;
    public readonly updatedAt!: Date;

    public async hasLike(userId: number): Promise<boolean> {
        if (!this.likers) {
            const like = await CirclePostLike.findOne({
                where: {
                    circlePostId: this.id,
                    userId: userId,
                },
            });
            return !!like;
        } else {
            return this.likers.some(liker => liker.id === userId);
        }
    }

    public async addLike(userId: number): Promise<void> {
        const [like, created] = await CirclePostLike.findOrCreate({
            where: {
                circlePostId: this.id,
                userId: userId,
            },
        });
        if (created) {
            await this.increment('likeCount');
        }
    }

    public async removeLike(userId: number): Promise<void> {
        const deletedCount = await CirclePostLike.destroy({
            where: {
                circlePostId: this.id,
                userId: userId,
            },
        });
        if (deletedCount > 0) {
            await this.decrement('likeCount');
        }
    }

    public static associate(models: { User: typeof User; Circle: typeof Circle; CirclePostLike: typeof CirclePostLike }) {
        CirclePost.belongsTo(models.User, {
            foreignKey: 'authorId',
            as: 'author',
        });

        CirclePost.belongsTo(models.Circle, {
            foreignKey: 'circleId',
            as: 'circle',
        });

        CirclePost.belongsToMany(models.User, {
            through: models.CirclePostLike,
            foreignKey: 'circlePostId',
            as: 'likers',
        });
    }
}

export function initCirclePost(sequelize: Sequelize) {
    CirclePost.init({
        id: {
            type: DataTypes.INTEGER.UNSIGNED,
            autoIncrement: true,
            primaryKey: true,
        },
        content: {
            type: new DataTypes.TEXT,
            allowNull: false,
        },
        images: {
            type: DataTypes.JSON,
            allowNull: true,
        },
        authorId: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
        },
        circleId: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
        },
        likeCount: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
            defaultValue: 0,
        },
        commentCount: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
            defaultValue: 0,
        },
        isTop: {
            type: DataTypes.BOOLEAN,
            allowNull: false,
            defaultValue: false,
        },
        isEssence: {
            type: DataTypes.BOOLEAN,
            allowNull: false,
            defaultValue: false,
        }
    }, {
        tableName: 'circle_posts',
        sequelize,
        timestamps: true,
    });
}

export default CirclePost; 